#include "filehelper.h"

#include "handle.h"
#include "stringutils.h"

bool FileHelper::ReadAllData(const String& fileName,
                             std::vector<unsigned char>& content) {
  if (fileName.compare("x64dbg://localhost/clipboard") != 0) {
    Handle hFile =
        CreateFileW(StringUtils::Utf8ToUtf16(fileName).c_str(), GENERIC_READ,
                    FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
    if (hFile == INVALID_HANDLE_VALUE) return false;
    unsigned int filesize = GetFileSize(hFile, nullptr);
    if (!filesize) {
      content.clear();
      return true;
    }
    content.resize(filesize);
    DWORD read = 0;
    return !!ReadFile(hFile, content.data(), filesize, &read, nullptr);
  } else {
    if (!OpenClipboard(0)) return false;
    HANDLE hData;
    hData = GetClipboardData(CF_UNICODETEXT);
    if (hData == NULL) {
      CloseClipboard();
      return false;
    }
    wchar_t* wideString = reinterpret_cast<wchar_t*>(GlobalLock(hData));
    if (wideString == nullptr) {
      CloseClipboard();
      return false;
    }
    String text = StringUtils::Utf16ToUtf8(wideString);
    GlobalUnlock(hData);
    CloseClipboard();
    content.resize(text.size());
    memcpy(content.data(), text.c_str(), text.size());
    return true;
  }
}

bool FileHelper::WriteAllData(const String& fileName, const void* data,
                              size_t size) {
  Handle hFile =
      CreateFileW(StringUtils::Utf8ToUtf16(fileName).c_str(), GENERIC_WRITE, 0,
                  nullptr, CREATE_ALWAYS, 0, nullptr);
  if (hFile == INVALID_HANDLE_VALUE) return false;
  DWORD written = 0;
  return !!WriteFile(hFile, data, DWORD(size), &written, nullptr);
}

bool FileHelper::ReadAllText(const String& fileName, String& content) {
  std::vector<unsigned char> data;
  if (!ReadAllData(fileName, data)) return false;
  data.push_back(0);
  content = String((const char*)data.data());
  return true;
}

bool FileHelper::WriteAllText(const String& fileName, const String& content) {
  return WriteAllData(fileName, content.c_str(), content.length());
}

bool FileHelper::ReadAllLines(const String& fileName,
                              std::vector<String>& lines, bool keepEmpty) {
  String content;
  if (!ReadAllText(fileName, content)) return false;
  lines.clear();
  String line;
  for (auto ch : content) {
    switch (ch) {
      case '\r':
        break;
      case '\n':
        if (line.length() || keepEmpty) lines.push_back(line);
        line.clear();
        break;
      default:
        line.resize(line.length() + 1);
        line[line.length() - 1] = ch;
        break;
    }
  }
  if (line.length()) lines.push_back(line);
  return true;
}

String FileHelper::GetFileName(const String& fileName) {
  auto last = strrchr(fileName.c_str(), '\\');
  return last ? last + 1 : fileName;
}
